Load Packages
First I need to load up the packages I’ll need
library(sf)
Linking to GEOS 3.4.2, GDAL 2.1.2, proj.4 4.9.1
library(ggplot2) #development version!
## devtools::install_github("tidyverse/ggplot2")
library(tidyverse)
Loading tidyverse: tibble
Loading tidyverse: tidyr
Loading tidyverse: readr
Loading tidyverse: purrr
Loading tidyverse: dplyr
Conflicts with tidy packages -----------------------------------------------------
filter(): dplyr, stats
lag(): dplyr, stats
library(readr)
## Not sure about this bit
#library("tidyverse",lib.loc="/Library/Frameworks/R.framework/Versions/3.4/Resources/library")
library(cowplot)
Attaching package: ‘cowplot’
The following object is masked from ‘package:ggplot2’:
ggsave
library(sp)
library(gridExtra)
Attaching package: ‘gridExtra’
The following object is masked from ‘package:dplyr’:
combine
Import Data
Now I import my data. I filter for the Arran postcodes, (since Arran all begins ‘KA27’).
## Finding the Arran coordinates
library(dplyr)
allcoordinates <- read.csv("alldata/ukpostcodes.csv")
arrancoordinates <- filter(allcoordinates,substr(postcode,1,4)=="KA27")
Plot Coordinates
Now I plot these coordinates.
## Plotting the Arran coordinates
ggplot(data = arrancoordinates) +
geom_point(mapping = aes(x = longitude, y = latitude), shape=20) +
ggtitle("Arran Postcodes") +
labs(title = "Arran Postcodes", x = "Longitude", y = "Latitude") +
theme(plot.title = element_text(hjust = 0.5)) +
theme_grey() +
coord_map()

Now I create some plots. #Arran Borders
pcs <- read_sf("alldata/Scotland_pcs_2011")
#Print Post codes lists
arransubsect <- filter(pcs,substr(label,1,4)=="KA27")
arransubsect %>%
ggplot() +
geom_sf() +
theme(axis.text.x=element_text(angle=45, hjust = 1)) +
theme_grey()

After a little editing I can overlay the two.
simple.sf <- st_as_sf(arrancoordinates, coords=c('longitude','latitude'))
st_crs(simple.sf) <- 4326
simple.sf %>%
ggplot() +
geom_sf(shape=20) +
theme_grey()

arransubsect %>%
ggplot() +
geom_sf() +
theme(axis.text.x=element_text(angle=45, hjust = 1)) +
theme_grey() +
geom_sf(data=simple.sf, shape=20)

Shape files
Now I can load the SIMD data, starting with the shape files.
#Import SIMD data from http://www.gov.scot/Topics/Statistics/SIMD
#The "new data zone boundaries with SIMD16 ranks (zipped shapefile)"
#'2011 Data Zone boundaries'
DZBoundaries2016 <- read_sf("./alldata/SG_SIMD_2016")
#https://data.gov.uk/dataset/scottish-index-of-multiple-deprivation-simd-2012
#https://data.gov.uk/dataset/scottish-index-of-multiple-deprivation-simd-2012/resource/d6fa8924-83da-4e80-a560-4ef0477f230b
DZBoundaries2012 <- read_sf("./alldata/SG_SIMD_2012")
DZBoundaries2009 <- read_sf("./alldata/SG_SIMD_2009")
DZBoundaries2006 <- read_sf("./alldata/SG_SIMD_2006")
DZBoundaries2004 <- read_sf("./alldata/SG_SIMD_2004")
Load SIMD data
Then (having already downloaded it), I can load the SIMD data.
#Look at data from 2016
SIMD2016 <-read.csv("./alldata/00505244.csv")
SIMD20162 <-read_sf("./alldata/SG_SIMD_2016")
#Look at data from 2012
SIMD2012 <- readxl::read_excel("./alldata/SIMD2012/00410770.xls")
SIMD20122 <- readxl::read_excel("./alldata/SIMD2012/00416552.xls")
#Look at data from 2009
SIMD2009 <- readxl::read_excel("./alldata/SIMD2009/0096578.xls")
SIMD20092 <- readxl::read_excel("./alldata/SIMD2009/0097806.xls")
#Look at data from 2006
# 2009 data - SIMD2006 <- readxl::read_excel("./alldata/SIMD2006/0096578.xls")
SIMD20062 <- readxl::read_excel("./alldata/SIMD2006/0097880.xls")
#Look at data from 2004
SIMD2004 <- readxl::read_excel("./alldata/SIMD2004/0027003.xls")
Select Arran SIMD data
I have to choose the right columns manually in order to select the Arran data.
#Selecting ArranDZ2016
Arrandz <- c(4672,4666,4669,4671,4667,4668,4670)
#Health domain rank
#2016
arran2016 <- SIMD20162[Arrandz,]
#Find postcode look-up, KA27 postcodes. Find unique DZ. Find row positions.
#Selecting ArranDZ2012
Arrandz2012 <- c(4409,4372,4353,4352,4351,4350,4349)
#2012
arran2012 <- DZBoundaries2012[Arrandz2012,]
#2009
arran2009 <- DZBoundaries2009[Arrandz2012,]
#2006
arran2006 <- DZBoundaries2006[Arrandz2012,]
#2004
arran2004 <- DZBoundaries2004[Arrandz2012,]
The reason I’ve downloaded all the datazones shapefiles individually (three steps up), is because they change between 2016 and 2012.
arran20162 <- arran2016 %>%
select(DataZone, geometry, Percentile) %>%
mutate(year="2016")
arran20122 <- arran2012 %>%
select(DataZone, geometry, Percentile) %>%
mutate(year="2012")
arran1612 <- rbind(arran20162,arran20122)
See the small difference.
arran1612 %>%
ggplot() +
geom_sf(aes(fill = DataZone)) +
facet_wrap('year') +
theme_grey() +
theme(legend.position="none") +
theme(axis.text.x=element_text(angle=45, hjust = 1))

Now I want to plot all the data, first I combine it all into one table. First I subselect the data I want from the appropriate columns.
arran20092 <- arran2009 %>%
select(DataZone, geometry, Percentile) %>%
mutate(year="2009")
arran20062 <- arran2006 %>%
select(DataZone, geometry, Percentile) %>%
mutate(year="2006")
arran20042 <- arran2004 %>%
select(DataZone, geometry, Percentile) %>%
mutate(year="2004")
arransimd <- rbind(arran20162,arran20122,arran20092,arran20062,arran20042)
Arran Percentile Plots
Now I plot the percentiles.
arransimd %>%
ggplot() +
geom_sf(aes(fill = Percentile)) +
facet_wrap('year') +
theme_grey() +
theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank(), axis.text.y=element_blank(),
axis.ticks.y=element_blank())

arransimd %>%
ggplot() +
geom_sf(aes(fill = Percentile)) +
facet_wrap('year', nrow = 1) +
theme_grey() +
theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank(), axis.text.y=element_blank(),
axis.ticks.y=element_blank())

There we are. Not the SIMD health percentiles of Arran zones throughout SIMD history. And I’ve learned a little bit about graphics in R.
If I wanted to I could show the zones individually..
First I find the unique zones. (There are 14. 7 Zones 2016, 7 Zones pre-2016)
datazones <- unique(arransimd$DataZone)
I’ll have to find out a simpler way to do this but..
Pre-2016 Individual Zones
S01004409 <- filter(arransimd, DataZone=="S01004409")
S01004372 <- filter(arransimd, DataZone=="S01004372")
S01004353 <- filter(arransimd, DataZone=="S01004353")
S01004352 <- filter(arransimd, DataZone=="S01004352")
S01004351 <- filter(arransimd, DataZone=="S01004351")
S01004350 <- filter(arransimd, DataZone=="S01004350")
S01004349 <- filter(arransimd, DataZone=="S01004349")
pre2016list <- list(S01004409, S01004372, S01004353, S01004352, S01004351, S01004350, S01004349)
function1 <- function(argument)
{
argument %>%
ggplot() +
geom_sf(aes(fill = Percentile)) +
facet_wrap('year') +
theme_grey() +
theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank())
}
function2 <- function(argument)
{
arransubsect %>%
ggplot() +
geom_sf() +
theme_grey() +
theme(axis.text.x=element_text(angle=45, hjust = 1)) +
geom_sf(data= argument, aes(fill = DataZone))
}
function3 <- function(argument)
{
argument %>%
ggplot() +
geom_sf(data = arransubsect) +
geom_sf(aes(fill = Percentile)) +
facet_wrap('year') +
theme_grey() +
theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank())
}
function4 <- function(argument)
{
plot_grid((function1(argument)), (function2(argument)), labels = c("A", "B"))
}
lapply(pre2016list, function4)
[[1]]
[[2]]
[[3]]
[[4]]
[[5]]
[[6]]
[[7]]







2016
Now I apply the same functions to the post-2016 Zones
arransubsect <- filter(pcs,substr(label,1,4)=="KA27")
S01011177 <- filter(arransimd, DataZone=="S01011177")
S01011171 <- filter(arransimd, DataZone=="S01011171")
S01011174 <- filter(arransimd, DataZone=="S01011174")
S01011176 <- filter(arransimd, DataZone=="S01011176")
S01011172 <- filter(arransimd, DataZone=="S01011172")
S01011173 <- filter(arransimd, DataZone=="S01011173")
S01011175 <- filter(arransimd, DataZone=="S01011175")
post2016list <- list(S01011177, S01011171, S01011174, S01011176, S01011172, S01011173, S01011175)
lapply(pre2016list, function4)
[[1]]
[[2]]
[[3]]
[[4]]
[[5]]
[[6]]
[[7]]







Plot the percentiles as bar charts.
Pre-2016
arransimd2 <- dplyr::filter(arransimd, year < 2016)
arransimd2 %>%
ggplot(aes(x=year, y=Percentile)) +
geom_bar(stat="identity") +
facet_wrap('DataZone') +
theme_grey() +
labs(title = "Arran SIMD Datazones", x = "Year", y = "Percentile") +
theme(plot.title = element_text(hjust = 0.5))

Post-2016
arransimd3 <- dplyr::filter(arransimd, year >= 2016)
arransimd3 %>%
ggplot(aes(x=year, y=Percentile)) +
geom_bar(stat="identity") +
facet_wrap('DataZone') +
theme_grey() +
labs(title = "Arran SIMD Datazones", x = "Year", y = "Percentile") +
theme(plot.title = element_text(hjust = 0.5))

Now I want to overlay the postcodes for a particular shapefile, in this case by Datazone. To do this I’ve converted both the Arran coordinates and Arran (2016) shapefiles into Spatial Points/Polygons, converted them into a common CRS, and then compared them by using over().
exampleshapes <- sf:::as_Spatial(arran2016$geom)
examplepoints <- sf:::as_Spatial(simple.sf$geom)
examplepoints <- spTransform(examplepoints, CRS("+proj=longlat +datum=WGS84"))
exampleshapes <- spTransform(exampleshapes, CRS("+proj=longlat +datum=WGS84"))
namingdzpostcode <- over(exampleshapes, examplepoints, returnList = TRUE)
I can then take a member reference from the orginal postcode list, which gives me a selection of the rows in that DZ. For simplicity I’ve written this as a new function.
Unfortunately, I haven’t worked out how to coordinate the new ID with the original DZ names yet, so I have to select by using the appropriate ID for each DZ. #Function selecting simple.sf by DZ ID.
function6 <- function(argument)
{
simple.sf[namingdzpostcode[[argument]],]
}
I can then use the above, and plot over the appropriate DZ shapefile. e.g
Projecting the coordinate selections
function1(S01004372) +
geom_sf(data=function6(2), shape=20)

function2(S01004372) +
geom_sf(data=function6(2), shape=20)

function3(S01004372) +
geom_sf(data=function6(2), shape=20)

If I edit function 4 a little so that the geom_sf layer is a second argument then I can also use function 4.
function4.5 <- function(argument, argument2)
{
a <- function1(argument)
b <- function2(argument) +
geom_sf(data=function6(argument2), shape=20)
plot_grid(a, b, labels = c("A", "B"))
}
function4.5(S01004372,2)

I’ve also made another function to plot the DZ on it’s own with coordinates.
function5 <- function(argument, argument2)
{
argument %>%
ggplot() +
geom_sf() +
theme_grey() +
geom_sf(data=function6(argument2), shape=20) +
theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank())
}
function5(S01004372,2)

function1.5 <- function(argument)
{
argument %>%
ggplot() +
geom_sf(aes(fill = Percentile)) +
facet_wrap('year') +
theme_grey() +
theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank()) +
theme(legend.position="bottom")
}
function2.5 <- function(argument)
{
arransubsect %>%
ggplot() +
geom_sf() +
theme_grey() +
theme(axis.text.x=element_text(angle=45, hjust = 1)) +
theme(legend.position="none") +
geom_sf(data= argument, aes(fill = DataZone))
}
function7.5 <- function(argument, argument2)
{
a <- function1.5(argument)
b <- function2.5(argument)
c <- function5(argument, argument2)
grid.arrange(a, b, c, nrow = 1)
}
function7.5(S01004372,2)

annotate percentile!
plot text of percentile, at centre of shape file coordinates.
LS0tCnRpdGxlOiAiQXJyYW4iCm91dHB1dDoKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KCiNMb2FkIFBhY2thZ2VzCkZpcnN0IEkgbmVlZCB0byBsb2FkIHVwIHRoZSBwYWNrYWdlcyBJJ2xsIG5lZWQKYGBge3J9CmxpYnJhcnkoc2YpCmxpYnJhcnkoZ2dwbG90MikgI2RldmVsb3BtZW50IHZlcnNpb24hCiMjIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigidGlkeXZlcnNlL2dncGxvdDIiKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkcikKIyMgTm90IHN1cmUgYWJvdXQgdGhpcyBiaXQKI2xpYnJhcnkoInRpZHl2ZXJzZSIsbGliLmxvYz0iL0xpYnJhcnkvRnJhbWV3b3Jrcy9SLmZyYW1ld29yay9WZXJzaW9ucy8zLjQvUmVzb3VyY2VzL2xpYnJhcnkiKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoc3ApCmxpYnJhcnkoZ3JpZEV4dHJhKQpgYGAKCiNJbXBvcnQgRGF0YQpOb3cgSSBpbXBvcnQgbXkgZGF0YS4gSSBmaWx0ZXIgZm9yIHRoZSBBcnJhbiBwb3N0Y29kZXMsIChzaW5jZSBBcnJhbiBhbGwgYmVnaW5zICdLQTI3JykuCmBgYHtyfQojIyBGaW5kaW5nIHRoZSBBcnJhbiBjb29yZGluYXRlcwpsaWJyYXJ5KGRwbHlyKQphbGxjb29yZGluYXRlcyA8LSByZWFkLmNzdigiYWxsZGF0YS91a3Bvc3Rjb2Rlcy5jc3YiKQphcnJhbmNvb3JkaW5hdGVzIDwtIGZpbHRlcihhbGxjb29yZGluYXRlcyxzdWJzdHIocG9zdGNvZGUsMSw0KT09IktBMjciKQpgYGAKCiNQbG90IENvb3JkaW5hdGVzCk5vdyBJIHBsb3QgdGhlc2UgY29vcmRpbmF0ZXMuCmBgYHtyfQojIyBQbG90dGluZyB0aGUgQXJyYW4gY29vcmRpbmF0ZXMKZ2dwbG90KGRhdGEgPSBhcnJhbmNvb3JkaW5hdGVzKSArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIHNoYXBlPTIwKSArCiAgZ2d0aXRsZSgiQXJyYW4gUG9zdGNvZGVzIikgKwogIGxhYnModGl0bGUgPSAiQXJyYW4gUG9zdGNvZGVzIiwgeCA9ICJMb25naXR1ZGUiLCB5ID0gIkxhdGl0dWRlIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArCiAgdGhlbWVfZ3JleSgpICsKICBjb29yZF9tYXAoKQpgYGAKCk5vdyBJIGNyZWF0ZSBzb21lIHBsb3RzLgojQXJyYW4gQm9yZGVycwpgYGB7cn0KcGNzIDwtIHJlYWRfc2YoImFsbGRhdGEvU2NvdGxhbmRfcGNzXzIwMTEiKQoKI1ByaW50IFBvc3QgY29kZXMgbGlzdHMKYXJyYW5zdWJzZWN0IDwtIGZpbHRlcihwY3Msc3Vic3RyKGxhYmVsLDEsNCk9PSJLQTI3IikKYXJyYW5zdWJzZWN0ICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKCkgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lX2dyZXkoKQpgYGAKCkFmdGVyIGEgbGl0dGxlIGVkaXRpbmcgSSBjYW4gb3ZlcmxheSB0aGUgdHdvLgpgYGB7cn0Kc2ltcGxlLnNmIDwtIHN0X2FzX3NmKGFycmFuY29vcmRpbmF0ZXMsIGNvb3Jkcz1jKCdsb25naXR1ZGUnLCdsYXRpdHVkZScpKQpzdF9jcnMoc2ltcGxlLnNmKSA8LSA0MzI2CmBgYAoKYGBge3J9CnNpbXBsZS5zZiAlPiUgCiAgZ2dwbG90KCkgKyAKICBnZW9tX3NmKHNoYXBlPTIwKSArCiAgdGhlbWVfZ3JleSgpIApgYGAKCmBgYHtyfQphcnJhbnN1YnNlY3QgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdCA9IDEpKSArCiAgdGhlbWVfZ3JleSgpICsKICBnZW9tX3NmKGRhdGE9c2ltcGxlLnNmLCBzaGFwZT0yMCkKYGBgCgojU2hhcGUgZmlsZXMKTm93IEkgY2FuIGxvYWQgdGhlIFNJTUQgZGF0YSwgc3RhcnRpbmcgd2l0aCB0aGUgc2hhcGUgZmlsZXMuCmBgYHtyfQojSW1wb3J0IFNJTUQgZGF0YSBmcm9tIGh0dHA6Ly93d3cuZ292LnNjb3QvVG9waWNzL1N0YXRpc3RpY3MvU0lNRAojVGhlICJuZXcgZGF0YSB6b25lIGJvdW5kYXJpZXMgd2l0aCBTSU1EMTYgcmFua3MgKHppcHBlZCBzaGFwZWZpbGUpIgojJzIwMTEgRGF0YSBab25lIGJvdW5kYXJpZXMnCgpEWkJvdW5kYXJpZXMyMDE2IDwtIHJlYWRfc2YoIi4vYWxsZGF0YS9TR19TSU1EXzIwMTYiKQoKI2h0dHBzOi8vZGF0YS5nb3YudWsvZGF0YXNldC9zY290dGlzaC1pbmRleC1vZi1tdWx0aXBsZS1kZXByaXZhdGlvbi1zaW1kLTIwMTIKI2h0dHBzOi8vZGF0YS5nb3YudWsvZGF0YXNldC9zY290dGlzaC1pbmRleC1vZi1tdWx0aXBsZS1kZXByaXZhdGlvbi1zaW1kLTIwMTIvcmVzb3VyY2UvZDZmYTg5MjQtODNkYS00ZTgwLWE1NjAtNGVmMDQ3N2YyMzBiCkRaQm91bmRhcmllczIwMTIgPC0gcmVhZF9zZigiLi9hbGxkYXRhL1NHX1NJTURfMjAxMiIpCkRaQm91bmRhcmllczIwMDkgPC0gcmVhZF9zZigiLi9hbGxkYXRhL1NHX1NJTURfMjAwOSIpCkRaQm91bmRhcmllczIwMDYgPC0gcmVhZF9zZigiLi9hbGxkYXRhL1NHX1NJTURfMjAwNiIpCkRaQm91bmRhcmllczIwMDQgPC0gcmVhZF9zZigiLi9hbGxkYXRhL1NHX1NJTURfMjAwNCIpCmBgYAoKI0xvYWQgU0lNRCBkYXRhClRoZW4gKGhhdmluZyBhbHJlYWR5IGRvd25sb2FkZWQgaXQpLCBJIGNhbiBsb2FkIHRoZSBTSU1EIGRhdGEuCmBgYHtyfQojTG9vayBhdCBkYXRhIGZyb20gMjAxNgpTSU1EMjAxNiA8LXJlYWQuY3N2KCIuL2FsbGRhdGEvMDA1MDUyNDQuY3N2IikKU0lNRDIwMTYyIDwtcmVhZF9zZigiLi9hbGxkYXRhL1NHX1NJTURfMjAxNiIpCgojTG9vayBhdCBkYXRhIGZyb20gMjAxMgpTSU1EMjAxMiA8LSByZWFkeGw6OnJlYWRfZXhjZWwoIi4vYWxsZGF0YS9TSU1EMjAxMi8wMDQxMDc3MC54bHMiKQpTSU1EMjAxMjIgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCIuL2FsbGRhdGEvU0lNRDIwMTIvMDA0MTY1NTIueGxzIikKCiNMb29rIGF0IGRhdGEgZnJvbSAyMDA5ClNJTUQyMDA5IDwtIHJlYWR4bDo6cmVhZF9leGNlbCgiLi9hbGxkYXRhL1NJTUQyMDA5LzAwOTY1NzgueGxzIikKU0lNRDIwMDkyIDwtIHJlYWR4bDo6cmVhZF9leGNlbCgiLi9hbGxkYXRhL1NJTUQyMDA5LzAwOTc4MDYueGxzIikKCiNMb29rIGF0IGRhdGEgZnJvbSAyMDA2CiMgMjAwOSBkYXRhIC0gU0lNRDIwMDYgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCIuL2FsbGRhdGEvU0lNRDIwMDYvMDA5NjU3OC54bHMiKQpTSU1EMjAwNjIgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCIuL2FsbGRhdGEvU0lNRDIwMDYvMDA5Nzg4MC54bHMiKQoKI0xvb2sgYXQgZGF0YSBmcm9tIDIwMDQKU0lNRDIwMDQgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCIuL2FsbGRhdGEvU0lNRDIwMDQvMDAyNzAwMy54bHMiKQpgYGAKCiNTZWxlY3QgQXJyYW4gU0lNRCBkYXRhCkkgaGF2ZSB0byBjaG9vc2UgdGhlIHJpZ2h0IGNvbHVtbnMgbWFudWFsbHkgaW4gb3JkZXIgdG8gc2VsZWN0IHRoZSBBcnJhbiBkYXRhLgpgYGB7cn0KI1NlbGVjdGluZyBBcnJhbkRaMjAxNgpBcnJhbmR6IDwtIGMoNDY3Miw0NjY2LDQ2NjksNDY3MSw0NjY3LDQ2NjgsNDY3MCkKCiNIZWFsdGggZG9tYWluIHJhbmsKIzIwMTYKYXJyYW4yMDE2IDwtIFNJTUQyMDE2MltBcnJhbmR6LF0KCiNGaW5kIHBvc3Rjb2RlIGxvb2stdXAsIEtBMjcgcG9zdGNvZGVzLiBGaW5kIHVuaXF1ZSBEWi4gRmluZCByb3cgcG9zaXRpb25zLgoKI1NlbGVjdGluZyBBcnJhbkRaMjAxMgpBcnJhbmR6MjAxMiA8LSBjKDQ0MDksNDM3Miw0MzUzLDQzNTIsNDM1MSw0MzUwLDQzNDkpCgojMjAxMgphcnJhbjIwMTIgPC0gRFpCb3VuZGFyaWVzMjAxMltBcnJhbmR6MjAxMixdCiMyMDA5CmFycmFuMjAwOSA8LSBEWkJvdW5kYXJpZXMyMDA5W0FycmFuZHoyMDEyLF0KIzIwMDYKYXJyYW4yMDA2IDwtIERaQm91bmRhcmllczIwMDZbQXJyYW5kejIwMTIsXQojMjAwNAphcnJhbjIwMDQgPC0gRFpCb3VuZGFyaWVzMjAwNFtBcnJhbmR6MjAxMixdCmBgYAoKVGhlIHJlYXNvbiBJJ3ZlIGRvd25sb2FkZWQgYWxsIHRoZSBkYXRhem9uZXMgc2hhcGVmaWxlcyBpbmRpdmlkdWFsbHkgKHRocmVlIHN0ZXBzIHVwKSwgaXMgYmVjYXVzZSB0aGV5IGNoYW5nZSBiZXR3ZWVuIDIwMTYgYW5kIDIwMTIuCgpgYGB7cn0KYXJyYW4yMDE2MiA8LSBhcnJhbjIwMTYgJT4lCiAgc2VsZWN0KERhdGFab25lLCBnZW9tZXRyeSwgUGVyY2VudGlsZSkgICU+JQogIG11dGF0ZSh5ZWFyPSIyMDE2IikKCmFycmFuMjAxMjIgPC0gYXJyYW4yMDEyICU+JQogIHNlbGVjdChEYXRhWm9uZSwgZ2VvbWV0cnksIFBlcmNlbnRpbGUpICU+JQogIG11dGF0ZSh5ZWFyPSIyMDEyIikKCmFycmFuMTYxMiA8LSByYmluZChhcnJhbjIwMTYyLGFycmFuMjAxMjIpCmBgYAoKU2VlIHRoZSBzbWFsbCBkaWZmZXJlbmNlLgpgYGB7cn0KYXJyYW4xNjEyICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gRGF0YVpvbmUpKSArCiAgZmFjZXRfd3JhcCgneWVhcicpICsKICB0aGVtZV9ncmV5KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0ID0gMSkpCmBgYAoKTm93IEkgd2FudCB0byBwbG90IGFsbCB0aGUgZGF0YSwgZmlyc3QgSSBjb21iaW5lIGl0IGFsbCBpbnRvIG9uZSB0YWJsZS4KRmlyc3QgSSBzdWJzZWxlY3QgdGhlIGRhdGEgSSB3YW50IGZyb20gdGhlIGFwcHJvcHJpYXRlIGNvbHVtbnMuCmBgYHtyfQphcnJhbjIwMDkyIDwtIGFycmFuMjAwOSAlPiUKICBzZWxlY3QoRGF0YVpvbmUsIGdlb21ldHJ5LCBQZXJjZW50aWxlKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAwOSIpCgphcnJhbjIwMDYyIDwtIGFycmFuMjAwNiAlPiUKICBzZWxlY3QoRGF0YVpvbmUsIGdlb21ldHJ5LCBQZXJjZW50aWxlKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAwNiIpCgphcnJhbjIwMDQyIDwtIGFycmFuMjAwNCAlPiUKICBzZWxlY3QoRGF0YVpvbmUsIGdlb21ldHJ5LCBQZXJjZW50aWxlKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAwNCIpCgphcnJhbnNpbWQgPC0gcmJpbmQoYXJyYW4yMDE2MixhcnJhbjIwMTIyLGFycmFuMjAwOTIsYXJyYW4yMDA2MixhcnJhbjIwMDQyKQpgYGAKCiNBcnJhbiBQZXJjZW50aWxlIFBsb3RzCk5vdyBJIHBsb3QgdGhlIHBlcmNlbnRpbGVzLgpgYGB7cn0KYXJyYW5zaW1kICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gUGVyY2VudGlsZSkpICsKICBmYWNldF93cmFwKCd5ZWFyJykgKwogIHRoZW1lX2dyZXkoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyfQphcnJhbnNpbWQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBQZXJjZW50aWxlKSkgKwogIGZhY2V0X3dyYXAoJ3llYXInLCBucm93ID0gMSkgKwogIHRoZW1lX2dyZXkoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQpgYGAKClRoZXJlIHdlIGFyZS4gTm90IHRoZSBTSU1EIGhlYWx0aCBwZXJjZW50aWxlcyBvZiBBcnJhbiB6b25lcyB0aHJvdWdob3V0IFNJTUQgaGlzdG9yeS4gQW5kIEkndmUgbGVhcm5lZCBhIGxpdHRsZSBiaXQgYWJvdXQgZ3JhcGhpY3MgaW4gUi4KCklmIEkgd2FudGVkIHRvIEkgY291bGQgc2hvdyB0aGUgem9uZXMgaW5kaXZpZHVhbGx5Li4KCkZpcnN0IEkgZmluZCB0aGUgdW5pcXVlIHpvbmVzLiAoVGhlcmUgYXJlIDE0LiA3IFpvbmVzIDIwMTYsIDcgWm9uZXMgcHJlLTIwMTYpCgpgYGB7cn0KZGF0YXpvbmVzIDwtIHVuaXF1ZShhcnJhbnNpbWQkRGF0YVpvbmUpCmBgYAoKSSdsbCBoYXZlIHRvIGZpbmQgb3V0IGEgc2ltcGxlciB3YXkgdG8gZG8gdGhpcyBidXQuLgoKI1ByZS0yMDE2IEluZGl2aWR1YWwgWm9uZXMKYGBge3J9ClMwMTAwNDQwOSA8LSBmaWx0ZXIoYXJyYW5zaW1kLCBEYXRhWm9uZT09IlMwMTAwNDQwOSIpClMwMTAwNDM3MiA8LSBmaWx0ZXIoYXJyYW5zaW1kLCBEYXRhWm9uZT09IlMwMTAwNDM3MiIpClMwMTAwNDM1MyA8LSBmaWx0ZXIoYXJyYW5zaW1kLCBEYXRhWm9uZT09IlMwMTAwNDM1MyIpClMwMTAwNDM1MiA8LSBmaWx0ZXIoYXJyYW5zaW1kLCBEYXRhWm9uZT09IlMwMTAwNDM1MiIpClMwMTAwNDM1MSA8LSBmaWx0ZXIoYXJyYW5zaW1kLCBEYXRhWm9uZT09IlMwMTAwNDM1MSIpClMwMTAwNDM1MCA8LSBmaWx0ZXIoYXJyYW5zaW1kLCBEYXRhWm9uZT09IlMwMTAwNDM1MCIpClMwMTAwNDM0OSA8LSBmaWx0ZXIoYXJyYW5zaW1kLCBEYXRhWm9uZT09IlMwMTAwNDM0OSIpCmBgYAoKYGBge3J9CnByZTIwMTZsaXN0IDwtIGxpc3QoUzAxMDA0NDA5LCBTMDEwMDQzNzIsIFMwMTAwNDM1MywgUzAxMDA0MzUyLCBTMDEwMDQzNTEsIFMwMTAwNDM1MCwgUzAxMDA0MzQ5KQpgYGAKCmBgYHtyfQpmdW5jdGlvbjEgPC0gZnVuY3Rpb24oYXJndW1lbnQpIAp7CiAgYXJndW1lbnQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBQZXJjZW50aWxlKSkgKwogIGZhY2V0X3dyYXAoJ3llYXInKSArCiAgdGhlbWVfZ3JleSgpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSkKfQpgYGAKCmBgYHtyfQpmdW5jdGlvbjIgPC0gZnVuY3Rpb24oYXJndW1lbnQpIAp7CiAgYXJyYW5zdWJzZWN0ICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKCkgKwogIHRoZW1lX2dyZXkoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdCA9IDEpKSArCiAgZ2VvbV9zZihkYXRhPSBhcmd1bWVudCwgYWVzKGZpbGwgPSBEYXRhWm9uZSkpCn0KYGBgCgpgYGB7cn0KZnVuY3Rpb24zIDwtIGZ1bmN0aW9uKGFyZ3VtZW50KSAKewogIGFyZ3VtZW50ICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGRhdGEgPSBhcnJhbnN1YnNlY3QpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gUGVyY2VudGlsZSkpICsKICBmYWNldF93cmFwKCd5ZWFyJykgKwogIHRoZW1lX2dyZXkoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpCn0KYGBgCgpgYGB7cn0KZnVuY3Rpb240IDwtIGZ1bmN0aW9uKGFyZ3VtZW50KSAKewogIHBsb3RfZ3JpZCgoZnVuY3Rpb24xKGFyZ3VtZW50KSksIChmdW5jdGlvbjIoYXJndW1lbnQpKSwgbGFiZWxzID0gYygiQSIsICJCIikpCn0KYGBgCgpgYGB7cn0KbGFwcGx5KHByZTIwMTZsaXN0LCBmdW5jdGlvbjQpCmBgYAoKIzIwMTYKTm93IEkgYXBwbHkgdGhlIHNhbWUgZnVuY3Rpb25zIHRvIHRoZSBwb3N0LTIwMTYgWm9uZXMKYGBge3J9CmFycmFuc3Vic2VjdCA8LSBmaWx0ZXIocGNzLHN1YnN0cihsYWJlbCwxLDQpPT0iS0EyNyIpCgpTMDEwMTExNzcgPC0gZmlsdGVyKGFycmFuc2ltZCwgRGF0YVpvbmU9PSJTMDEwMTExNzciKQpTMDEwMTExNzEgPC0gZmlsdGVyKGFycmFuc2ltZCwgRGF0YVpvbmU9PSJTMDEwMTExNzEiKQpTMDEwMTExNzQgPC0gZmlsdGVyKGFycmFuc2ltZCwgRGF0YVpvbmU9PSJTMDEwMTExNzQiKQpTMDEwMTExNzYgPC0gZmlsdGVyKGFycmFuc2ltZCwgRGF0YVpvbmU9PSJTMDEwMTExNzYiKQpTMDEwMTExNzIgPC0gZmlsdGVyKGFycmFuc2ltZCwgRGF0YVpvbmU9PSJTMDEwMTExNzIiKQpTMDEwMTExNzMgPC0gZmlsdGVyKGFycmFuc2ltZCwgRGF0YVpvbmU9PSJTMDEwMTExNzMiKQpTMDEwMTExNzUgPC0gZmlsdGVyKGFycmFuc2ltZCwgRGF0YVpvbmU9PSJTMDEwMTExNzUiKQpgYGAKCmBgYHtyfQpwb3N0MjAxNmxpc3QgPC0gbGlzdChTMDEwMTExNzcsIFMwMTAxMTE3MSwgUzAxMDExMTc0LCBTMDEwMTExNzYsIFMwMTAxMTE3MiwgUzAxMDExMTczLCBTMDEwMTExNzUpCmBgYAoKYGBge3J9CmxhcHBseShwcmUyMDE2bGlzdCwgZnVuY3Rpb240KQpgYGAKCiNQbG90IHRoZSBwZXJjZW50aWxlcyBhcyBiYXIgY2hhcnRzLgoKUHJlLTIwMTYKYGBge3J9CmFycmFuc2ltZDIgPC0gZHBseXI6OmZpbHRlcihhcnJhbnNpbWQsIHllYXIgPCAyMDE2KQoKYXJyYW5zaW1kMiAlPiUKZ2dwbG90KGFlcyh4PXllYXIsIHk9UGVyY2VudGlsZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICBmYWNldF93cmFwKCdEYXRhWm9uZScpICsKICB0aGVtZV9ncmV5KCkgKwogIGxhYnModGl0bGUgPSAiQXJyYW4gU0lNRCBEYXRhem9uZXMiLCB4ID0gIlllYXIiLCB5ID0gIlBlcmNlbnRpbGUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYAoKUG9zdC0yMDE2CmBgYHtyfQphcnJhbnNpbWQzIDwtIGRwbHlyOjpmaWx0ZXIoYXJyYW5zaW1kLCB5ZWFyID49IDIwMTYpCgphcnJhbnNpbWQzICU+JQpnZ3Bsb3QoYWVzKHg9eWVhciwgeT1QZXJjZW50aWxlKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKwogIGZhY2V0X3dyYXAoJ0RhdGFab25lJykgKwogIHRoZW1lX2dyZXkoKSArCiAgbGFicyh0aXRsZSA9ICJBcnJhbiBTSU1EIERhdGF6b25lcyIsIHggPSAiWWVhciIsIHkgPSAiUGVyY2VudGlsZSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgpOb3cgSSB3YW50IHRvIG92ZXJsYXkgdGhlIHBvc3Rjb2RlcyBmb3IgYSBwYXJ0aWN1bGFyIHNoYXBlZmlsZSwgaW4gdGhpcyBjYXNlIGJ5IERhdGF6b25lLgpUbyBkbyB0aGlzIEkndmUgY29udmVydGVkIGJvdGggdGhlIEFycmFuIGNvb3JkaW5hdGVzIGFuZCBBcnJhbiAoMjAxNikgc2hhcGVmaWxlcyBpbnRvIFNwYXRpYWwgUG9pbnRzL1BvbHlnb25zLCBjb252ZXJ0ZWQgdGhlbSBpbnRvIGEgY29tbW9uIENSUywgYW5kIHRoZW4gY29tcGFyZWQgdGhlbSBieSB1c2luZyBvdmVyKCkuCmBgYHtyfQpleGFtcGxlc2hhcGVzIDwtIHNmOjo6YXNfU3BhdGlhbChhcnJhbjIwMTYkZ2VvbSkKZXhhbXBsZXBvaW50cyA8LSBzZjo6OmFzX1NwYXRpYWwoc2ltcGxlLnNmJGdlb20pCgpleGFtcGxlcG9pbnRzIDwtIHNwVHJhbnNmb3JtKGV4YW1wbGVwb2ludHMsIENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKZXhhbXBsZXNoYXBlcyA8LSBzcFRyYW5zZm9ybShleGFtcGxlc2hhcGVzLCBDUlMoIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0IikpCgpuYW1pbmdkenBvc3Rjb2RlIDwtIG92ZXIoZXhhbXBsZXNoYXBlcywgZXhhbXBsZXBvaW50cywgcmV0dXJuTGlzdCA9IFRSVUUpCmBgYAoKSSBjYW4gdGhlbiB0YWtlIGEgbWVtYmVyIHJlZmVyZW5jZSBmcm9tIHRoZSBvcmdpbmFsIHBvc3Rjb2RlIGxpc3QsIHdoaWNoIGdpdmVzIG1lIGEgc2VsZWN0aW9uIG9mIHRoZSByb3dzIGluIHRoYXQgRFouIEZvciBzaW1wbGljaXR5IEkndmUgd3JpdHRlbiB0aGlzIGFzIGEgbmV3IGZ1bmN0aW9uLiAKClVuZm9ydHVuYXRlbHksIEkgaGF2ZW4ndCB3b3JrZWQgb3V0IGhvdyB0byBjb29yZGluYXRlIHRoZSBuZXcgSUQgd2l0aCB0aGUgb3JpZ2luYWwgRFogbmFtZXMgeWV0LCBzbyBJIGhhdmUgdG8gc2VsZWN0IGJ5IHVzaW5nIHRoZSBhcHByb3ByaWF0ZSBJRCBmb3IgZWFjaCBEWi4KI0Z1bmN0aW9uIHNlbGVjdGluZyBzaW1wbGUuc2YgYnkgRFogSUQuCmBgYHtyfQpmdW5jdGlvbjYgPC0gZnVuY3Rpb24oYXJndW1lbnQpIAp7CiAgc2ltcGxlLnNmW25hbWluZ2R6cG9zdGNvZGVbW2FyZ3VtZW50XV0sXQp9CmBgYAoKSSBjYW4gdGhlbiB1c2UgdGhlIGFib3ZlLCBhbmQgcGxvdCBvdmVyIHRoZSBhcHByb3ByaWF0ZSBEWiBzaGFwZWZpbGUuCmUuZwoKI1Byb2plY3RpbmcgdGhlIGNvb3JkaW5hdGUgc2VsZWN0aW9ucwpgYGB7cn0KZnVuY3Rpb24xKFMwMTAwNDM3MikgKwogIGdlb21fc2YoZGF0YT1mdW5jdGlvbjYoMiksIHNoYXBlPTIwKQpmdW5jdGlvbjIoUzAxMDA0MzcyKSArCiAgZ2VvbV9zZihkYXRhPWZ1bmN0aW9uNigyKSwgc2hhcGU9MjApCmZ1bmN0aW9uMyhTMDEwMDQzNzIpICsKICBnZW9tX3NmKGRhdGE9ZnVuY3Rpb242KDIpLCBzaGFwZT0yMCkKYGBgCgpJZiBJIGVkaXQgZnVuY3Rpb24gNCBhIGxpdHRsZSBzbyB0aGF0IHRoZSBnZW9tX3NmIGxheWVyIGlzIGEgc2Vjb25kIGFyZ3VtZW50IHRoZW4gSSBjYW4gYWxzbyB1c2UgZnVuY3Rpb24gNC4KCmBgYHtyfQpmdW5jdGlvbjQuNSA8LSBmdW5jdGlvbihhcmd1bWVudCwgYXJndW1lbnQyKSAKewogIGEgPC0gZnVuY3Rpb24xKGFyZ3VtZW50KQogIGIgPC0gZnVuY3Rpb24yKGFyZ3VtZW50KSArCiAgZ2VvbV9zZihkYXRhPWZ1bmN0aW9uNihhcmd1bWVudDIpLCBzaGFwZT0yMCkKCiAgcGxvdF9ncmlkKGEsIGIsIGxhYmVscyA9IGMoIkEiLCAiQiIpKQp9CmBgYAoKYGBge3J9CmZ1bmN0aW9uNC41KFMwMTAwNDM3MiwyKQpgYGAKCkkndmUgYWxzbyBtYWRlIGFub3RoZXIgZnVuY3Rpb24gdG8gcGxvdCB0aGUgRFogb24gaXQncyBvd24gd2l0aCBjb29yZGluYXRlcy4KYGBge3J9CmZ1bmN0aW9uNSA8LSBmdW5jdGlvbihhcmd1bWVudCwgYXJndW1lbnQyKSAKewogIGFyZ3VtZW50ICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKCkgKwogIHRoZW1lX2dyZXkoKSArCiAgZ2VvbV9zZihkYXRhPWZ1bmN0aW9uNihhcmd1bWVudDIpLCBzaGFwZT0yMCkgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpKQp9CmBgYAoKYGBge3J9CmZ1bmN0aW9uNShTMDEwMDQzNzIsMikKYGBgCgpgYGB7cn0KZnVuY3Rpb24xLjUgPC0gZnVuY3Rpb24oYXJndW1lbnQpIAp7CiAgYXJndW1lbnQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBQZXJjZW50aWxlKSkgKwogIGZhY2V0X3dyYXAoJ3llYXInKSArCiAgdGhlbWVfZ3JleSgpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgIAp9CmBgYAoKYGBge3J9CmZ1bmN0aW9uMi41IDwtIGZ1bmN0aW9uKGFyZ3VtZW50KSAKewogIGFycmFuc3Vic2VjdCAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZigpICsKICB0aGVtZV9ncmV5KCkgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZW9tX3NmKGRhdGE9IGFyZ3VtZW50LCBhZXMoZmlsbCA9IERhdGFab25lKSkKfQpgYGAKCmBgYHtyfQpmdW5jdGlvbjcuNSA8LSBmdW5jdGlvbihhcmd1bWVudCwgYXJndW1lbnQyKSAKewogIGEgPC0gZnVuY3Rpb24xLjUoYXJndW1lbnQpCiAgYiA8LSBmdW5jdGlvbjIuNShhcmd1bWVudCkgCiAgYyA8LSBmdW5jdGlvbjUoYXJndW1lbnQsIGFyZ3VtZW50MikKICBncmlkLmFycmFuZ2UoYSwgYiwgYywgbnJvdyA9IDEpCn0KYGBgCgpgYGB7cn0KZnVuY3Rpb243LjUoUzAxMDA0MzcyLDIpCmBgYAoKI2Fubm90YXRlIHBlcmNlbnRpbGUhCnBsb3QgdGV4dCBvZiBwZXJjZW50aWxlLCBhdCBjZW50cmUgb2Ygc2hhcGUgZmlsZSBjb29yZGluYXRlcy4K